package com.ruoyi.flow.flow.workflow;

import com.ruoyi.flow.flow.FlowConstants;
import com.ruoyi.flow.flow.workflow.FlowCondition;
import com.google.common.base.Joiner;
import com.google.common.collect.Maps;
import com.sun.el.ExpressionFactoryImpl;
import de.odysseus.el.util.SimpleContext;
import org.apache.commons.lang3.StringUtils;

import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @Author: wtian
 * @Description:
 * @Date: Created in 16:57 2018/8/9
 * @Version: 1.0
 */
public class FlowUtils {
    /**
     * 验证用户的表达式是否满足流程定义的表达式
     *
     * @param expression 流程定义的表达式
     * @return
     */
    public static boolean checkCondition(String expression, List<FlowCondition> flowConditions, Map<String, Object> variables) {
        boolean checked = false;
        ExpressionFactory expressionFactory = new ExpressionFactoryImpl();
        SimpleContext simpleContext = new SimpleContext();
        for (FlowCondition flowCondition : flowConditions) {
            String varValue = flowCondition.getVarValue();
            simpleContext.setVariable(flowCondition.getVarName(), expressionFactory.createValueExpression(varValue, String.class));
        }
        ValueExpression valueExpression = expressionFactory.createValueExpression(simpleContext, expression, Boolean.class);
        try {
            checked = (Boolean) valueExpression.getValue(simpleContext);
            return checked;
        } catch (Exception e) {
            if (variables == null || variables.isEmpty()) {
                throw e;
            } else {
                String msg = e.getMessage();
                String property = StringUtils.substringAfter(msg, "Cannot find property ");
                if (variables.containsKey(property)) {
                    FlowCondition flowCondition = new FlowCondition();
                    flowCondition.setVarName(property);
                    flowCondition.setVarValue(Objects.toString(variables.get(property)));
                    flowConditions.add(flowCondition);
                    return checkCondition(expression, flowConditions, variables);
                } else {
                    throw e;
                }
            }
        }
    }

    public static void mergeRequestToMap(Map<String, String[]> requests, Map variables) {
        for (Map.Entry<String, String[]> entry : requests.entrySet()) {
            String key = entry.getKey();
            String[] values = entry.getValue();
            if (values == null || values.length <= 0) {
                continue;
            }
            // 排除选择用户的参数
            if (StringUtils.equalsAny(key, FlowConstants.Assignee.SELECTMULTIGROUP.getAssignee(), FlowConstants.Assignee.SELECTSINGLEGROUP.getAssignee(), FlowConstants.Assignee.SELECTMULTIUSER.getAssignee(), FlowConstants.Assignee.SELECTSINGLEUSER.getAssignee())) {
                continue;
            }
            if (StringUtils.equalsAny(key, "assignees", "assigneeType")) {
                continue;
            }
            variables.put(key, Joiner.on(",").join(values));
        }
    }

    /**
     * 将request中的请求数据转乘{@code Map<String,String>}，用于表单发起流程
     *
     * @param request
     * @return
     */
    public static Map<String, String> getFormVariableFromRequest(HttpServletRequest request) {
        Map<String, String[]> requests = request.getParameterMap();
        Map<String, String> variables = Maps.newHashMap();
        FlowUtils.mergeRequestToMap(requests, variables);
        return variables;
    }

    /**
     * 将request中的请求数据转乘{@code Map<String,String>}，用于runtimeService发起流程
     *
     * @param request
     * @return
     */
    public static Map<String, Object> getProcessVariableFromRequest(HttpServletRequest request) {
        Map<String, String[]> requests = request.getParameterMap();
        Map<String, Object> variables = Maps.newHashMap();
        FlowUtils.mergeRequestToMap(requests, variables);
        return variables;
    }
}
